/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package haw.pr2.A1a;

/**
 *
 * @author abg659
 */
public class Porsche911GT2RS implements ParticleInterface {
    //Konstanten
    private final double KILO = 1000.0;
    private final double HOUR_IN_SEC = 3600.0;
    private final double KMH_IN_MS = KILO / HOUR_IN_SEC;
    
    private final double mass = 1445.0; // [kg]
    private final double powerPropMax = 456.0 * 1000.0; // [ ??] [W]
    private final double speedMax = 330.0 * 1000.0 / 3600.0; //km/h * 1000 /3600 = [ms^-1]
    private final double dragConst = Math.abs(powerPropMax / (Math.pow(speedMax, 3))); // W/(m/s)^3
    private final double accEarth = 9.81; // m/s^2
    private final double forcePropMax = mass * accEarth; //KG * m/s^2
    private final double YPos = 200.0; //Y-Position des Autos
    //Eigenschaften von Porsche
    private double speed = 0.0; // m/s
    private double level = 0.0;
    private double pos = 0.0; //Startposition
    //Eigenschaften von Umwelt
    private double time = 0.0; //vergangene Zeit in Sekunden
    private double acc = 0.0; // in m/s^2


    private void reset() {
        set(0.0, 0.0, 0.0, 0.0);
    }

    /*
     * Setzt die aktuellen Werte
     */
    private void set(double _time, double _pos, double _speed, double _level) {
        double force = 0.0;
        double forceProp = 0.0;
        double forceDrag = 0.0;
        double powerProp = 0.0;
        double forcePropAbs = 0.0;
        
        // Set globals
        this.speed = _speed; // m/s
        this.level = _level; // -1.0..+1.00
        this.pos = _pos; // X-Position
        this.time = _time; // in Sekunden
                
        powerProp = Math.abs(this.level) * this.powerPropMax; // -1.0..+1.0 * W
        forcePropAbs = Math.min(this.forcePropMax, (powerProp / Math.abs(this.speed))); // minimum( W ,  W / m/s )  
        forceProp = forcePropAbs * Math.signum(this.level); // minimum( W , W / (m/s) )
        forceDrag = this.dragConst * (Math.pow(this.speed, 2) * Math.signum(-this.speed)); // W / (m/s)^3 * ( (m/s)^2 * m/s ) = W
        force = forceProp + forceDrag; //  minimum ( W , W / (m/s))
        this.acc = force / this.mass; // minimum ( W / KG , m/s )
    }


    /*
     * Führt einen Simulationsschritt aus
     */
    public void step(double deltaTime, double _level) {
        double ltime; // in Sekunden
        double lpos; // X-Position
        double lspeed; // m/s
        
        ltime = this.time + deltaTime; // s

        lpos = this.pos + (this.speed * deltaTime); // m

        //Auto braucht eine Anfangsgeschwindigkeit um anfahren zu können
        lspeed = (this.speed == 0) ? 0.1 : this.speed + (this.acc * deltaTime); // m/s

        //Testausgabe
//        System.out.printf("Speed:" + lspeed * 3.6); //Testausgabe
//        System.out.println("\t\ttime:" + ltime); //Testausgabe
//        System.out.println("\t\tpos:" + lpos); //Testausgabe

        //Auto zurücksetzen wenn es am Ende angekommen ist
        if (lpos > 250) {
            lpos = 0;
        }
        
        set(ltime, lpos, lspeed, _level);
    }

    @Override
    public void simulateStep(double deltaTInSeconds) {
        step(deltaTInSeconds, 1.0);
    }

    @Override
    public double getXInMeters() {
        return this.pos;
    }
    
    @Override
    public double getYInMeters() {
        return this.YPos;
    }

    @Override
    public double getLevel() {
        return this.level;
    }

    @Override
    public double getSpeed() {
        return Math.round(this.speed * 3.6 * 100d) / 100d; // km/h
    }

    @Override
    public double getTime() {
        return Math.round(this.time * 100d) / 100d; //sek
    }
    
    @Override
    public String getName() {
        return this.getClass().getSimpleName();
    }
}
